from heap.class_klass import HeapObject
from insts.inst import NoOperandInstruction
from jthread.frame import JFrame


class XALOAD(NoOperandInstruction):

    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "XALOAD"

    def execute(self, frame: JFrame):
        stack = frame.getOperandStack()
        i = stack.popInt()
        arrRef: HeapObject = stack.popRef()
        if arrRef == None:
            raise Exception("java.lang.NullPointerException")
        bytes = arrRef.bytes()
        if i < 0 or i >= len(bytes):
            raise Exception("java.lang.ArrayIndexOutOfBoundsException")
        if self.kind == "int":
            stack.pushInt(bytes[i])
        elif self.kind == "float":
            stack.pushFloat(bytes[i])
        elif self.kind == "double":  # double is 8 bytes
            stack.pushDouble(bytes[i])
        else:
            stack.pushRef(bytes[i])


class BALOAD(XALOAD):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "int"


class CALOAD(XALOAD):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "int"


class DALOAD(XALOAD):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "double"


class FALOAD(XALOAD):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "float"


class IALOAD(XALOAD):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "int"


class LALOAD(XALOAD):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "long"


class SALOAD(XALOAD):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "int"


class AALOAD(XALOAD):
    def __init__(self, opcode):
        super().__init__(opcode)
        self.kind = "ref"
